using System.Diagnostics;
using System.Runtime;
using Microsoft.Data.SqlClient;
using Oracle.ManagedDataAccess.Client;

namespace Lzfy_Refund_Service.Services
{
    /// <summary>
    /// 应用程序健康检查服务
    /// </summary>
    public class ApplicationHealthCheckService : BackgroundService
    {
        private readonly ILogger<ApplicationHealthCheckService> _logger;
        private readonly IServiceProvider _serviceProvider;
        private readonly IDatabaseConfigurationService _dbConfigService;
        private readonly TimeSpan _checkInterval = TimeSpan.FromMinutes(1); // 每分钟检查一次
        
        // 健康状态
        private bool _isHealthy = true;
        private DateTime _lastHealthCheckTime = DateTime.MinValue;
        private readonly Dictionary<string, object> _healthMetrics = new();
        private readonly object _metricsLock = new object();

        public ApplicationHealthCheckService(
            ILogger<ApplicationHealthCheckService> logger,
            IServiceProvider serviceProvider,
            IDatabaseConfigurationService dbConfigService)
        {
            _logger = logger;
            _serviceProvider = serviceProvider;
            _dbConfigService = dbConfigService;
        }

        protected override async Task ExecuteAsync(CancellationToken stoppingToken)
        {
            _logger.LogInformation("应用健康检查服务启动");

            while (!stoppingToken.IsCancellationRequested)
            {
                try
                {
                    await PerformHealthCheckAsync();
                }
                catch (Exception ex)
                {
                    _logger.LogError(ex, "执行应用健康检查时发生异常");
                }

                try
                {
                    await Task.Delay(_checkInterval, stoppingToken);
                }
                catch (OperationCanceledException)
                {
                    break;
                }
            }

            _logger.LogInformation("应用健康检查服务停止");
        }

        /// <summary>
        /// 执行健康检查
        /// </summary>
        private async Task PerformHealthCheckAsync()
        {
            var healthStatus = new Dictionary<string, object>();
            bool overallHealth = true;

            try
            {
                // 1. 检查内存使用情况
                var memoryInfo = CheckMemoryUsage();
                healthStatus["memory"] = memoryInfo;
                if ((long)memoryInfo["usedMemoryMB"] > 1024) // 超过1GB警告
                {
                    _logger.LogWarning("内存使用量较高: {UsedMemory}MB", memoryInfo["usedMemoryMB"]);
                }

                // 2. 检查数据库连接
                var dbHealth = await CheckDatabaseHealthAsync();
                healthStatus["database"] = dbHealth;
                if (!(bool)dbHealth["sqlServerHealthy"] || !(bool)dbHealth["oracleHealthy"])
                {
                    overallHealth = false;
                    _logger.LogWarning("数据库连接异常");
                }

                // 3. 检查文件系统
                var fileSystemHealth = CheckFileSystemHealth();
                healthStatus["fileSystem"] = fileSystemHealth;
                if (!(bool)fileSystemHealth["isHealthy"])
                {
                    overallHealth = false;
                    _logger.LogWarning("文件系统异常");
                }

                // 4. 检查线程池状态
                var threadPoolInfo = CheckThreadPoolStatus();
                healthStatus["threadPool"] = threadPoolInfo;

                // 5. 检查GC状态
                var gcInfo = CheckGCStatus();
                healthStatus["gc"] = gcInfo;

                // 更新健康状态
                lock (_metricsLock)
                {
                    _isHealthy = overallHealth;
                    _lastHealthCheckTime = DateTime.Now;
                    _healthMetrics.Clear();
                    foreach (var kvp in healthStatus)
                    {
                        _healthMetrics[kvp.Key] = kvp.Value;
                    }
                }

                if (!overallHealth)
                {
                    _logger.LogWarning("应用健康检查发现问题，尝试自动恢复");
                    await AttemptAutoRecoveryAsync();
                }
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "健康检查执行失败");
                lock (_metricsLock)
                {
                    _isHealthy = false;
                }
            }
        }

        /// <summary>
        /// 检查内存使用情况
        /// </summary>
        private Dictionary<string, object> CheckMemoryUsage()
        {
            var process = Process.GetCurrentProcess();
            var gcInfo = GC.GetTotalMemory(false);
            
            return new Dictionary<string, object>
            {
                ["workingSetMB"] = process.WorkingSet64 / 1024 / 1024,
                ["usedMemoryMB"] = gcInfo / 1024 / 1024,
                ["gen0Collections"] = GC.CollectionCount(0),
                ["gen1Collections"] = GC.CollectionCount(1),
                ["gen2Collections"] = GC.CollectionCount(2)
            };
        }

        /// <summary>
        /// 检查数据库健康状态
        /// </summary>
        private async Task<Dictionary<string, object>> CheckDatabaseHealthAsync()
        {
            bool sqlServerHealthy = false;
            bool oracleHealthy = false;

            try
            {
                // 检查SQL Server
                using var sqlConn = new SqlConnection(_dbConfigService.GetDefaultConnection());
                await sqlConn.OpenAsync();
                using var sqlCmd = sqlConn.CreateCommand();
                sqlCmd.CommandText = "SELECT 1";
                sqlCmd.CommandTimeout = 5;
                await sqlCmd.ExecuteScalarAsync();
                sqlServerHealthy = true;
            }
            catch (Exception ex)
            {
                _logger.LogWarning(ex, "SQL Server连接检查失败");
            }

            try
            {
                // 检查Oracle
                using var oracleConn = new OracleConnection(_dbConfigService.GetHisOracleConnection());
                await oracleConn.OpenAsync();
                using var oracleCmd = oracleConn.CreateCommand();
                oracleCmd.CommandText = "SELECT 1 FROM DUAL";
                oracleCmd.CommandTimeout = 5;
                await oracleCmd.ExecuteScalarAsync();
                oracleHealthy = true;
            }
            catch (Exception ex)
            {
                _logger.LogWarning(ex, "Oracle连接检查失败");
            }

            return new Dictionary<string, object>
            {
                ["sqlServerHealthy"] = sqlServerHealthy,
                ["oracleHealthy"] = oracleHealthy,
                ["checkTime"] = DateTime.Now
            };
        }

        /// <summary>
        /// 检查文件系统健康状态
        /// </summary>
        private Dictionary<string, object> CheckFileSystemHealth()
        {
            bool isHealthy = true;
            var issues = new List<string>();

            try
            {
                // 检查上传目录
                var uploadPath = "d:\\upload\\images\\";
                if (!Directory.Exists(uploadPath))
                {
                    Directory.CreateDirectory(uploadPath);
                    _logger.LogInformation("创建上传目录: {Path}", uploadPath);
                }

                // 检查磁盘空间
                var driveInfo = new DriveInfo("D:");
                var freeSpaceGB = driveInfo.AvailableFreeSpace / 1024 / 1024 / 1024;
                if (freeSpaceGB < 1) // 少于1GB警告
                {
                    isHealthy = false;
                    issues.Add($"磁盘空间不足: {freeSpaceGB}GB");
                }

                return new Dictionary<string, object>
                {
                    ["isHealthy"] = isHealthy,
                    ["freeSpaceGB"] = freeSpaceGB,
                    ["issues"] = issues
                };
            }
            catch (Exception ex)
            {
                _logger.LogWarning(ex, "文件系统检查失败");
                return new Dictionary<string, object>
                {
                    ["isHealthy"] = false,
                    ["error"] = ex.Message
                };
            }
        }

        /// <summary>
        /// 检查线程池状态
        /// </summary>
        private Dictionary<string, object> CheckThreadPoolStatus()
        {
            ThreadPool.GetAvailableThreads(out int workerThreads, out int completionPortThreads);
            ThreadPool.GetMaxThreads(out int maxWorkerThreads, out int maxCompletionPortThreads);

            return new Dictionary<string, object>
            {
                ["availableWorkerThreads"] = workerThreads,
                ["availableCompletionPortThreads"] = completionPortThreads,
                ["maxWorkerThreads"] = maxWorkerThreads,
                ["maxCompletionPortThreads"] = maxCompletionPortThreads,
                ["busyWorkerThreads"] = maxWorkerThreads - workerThreads,
                ["busyCompletionPortThreads"] = maxCompletionPortThreads - completionPortThreads
            };
        }

        /// <summary>
        /// 检查GC状态
        /// </summary>
        private Dictionary<string, object> CheckGCStatus()
        {
            return new Dictionary<string, object>
            {
                ["totalMemory"] = GC.GetTotalMemory(false),
                ["gen0Collections"] = GC.CollectionCount(0),
                ["gen1Collections"] = GC.CollectionCount(1),
                ["gen2Collections"] = GC.CollectionCount(2),
                ["maxGeneration"] = GC.MaxGeneration
            };
        }

        /// <summary>
        /// 尝试自动恢复
        /// </summary>
        private async Task AttemptAutoRecoveryAsync()
        {
            try
            {
                // 1. 强制垃圾回收
                GC.Collect();
                GC.WaitForPendingFinalizers();
                GC.Collect();
                _logger.LogInformation("执行强制垃圾回收");

                // 2. 等待一段时间让系统恢复
                await Task.Delay(TimeSpan.FromSeconds(5));

                _logger.LogInformation("自动恢复尝试完成");
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "自动恢复失败");
            }
        }

        /// <summary>
        /// 获取当前健康状态
        /// </summary>
        public (bool IsHealthy, DateTime LastCheckTime, Dictionary<string, object> Metrics) GetHealthStatus()
        {
            lock (_metricsLock)
            {
                return (_isHealthy, _lastHealthCheckTime, new Dictionary<string, object>(_healthMetrics));
            }
        }
    }
}